/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       adv_move_booster.h

	$Header: /game/adv_move_booster.h $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "adv_move_booster.h"

#include "adv_object_type.h"
#include "adventure_ai.h"
#include "adventure_frame.h"
#include "adventure_map.h"
#include "adventure_sounds.h"
#include "army.h"
#include "basic_dialog.h"
#include "external_string.h"
#include "music.h"
#include "object_registration.h"
#include "player.h"
#include "terrain.h"

static t_object_registration<t_adv_move_booster> k_registration( k_adv_object_movement_booster );

static t_object_registration<t_adv_pathfinder> k_pathfinder_registration( k_adv_object_pathfinder );

// --------------------------------------------------------
// all objects which give an army a timed boost to movement
//  -------------------------------------------------------
t_adv_move_booster::t_adv_move_booster(  std::string const& source )
                  : t_stationary_adventure_object( source )
{
}

// --------------------------------------------------------
// all objects which give an army a timed boost to movement
//  -------------------------------------------------------
void t_adv_move_booster::show_dialog( t_army* army, int amount, int days, 
									  t_level_map_point_2d const& point ) const
{
	bool result;

	t_counted_ptr<t_basic_dialog> basic_dialog;

	basic_dialog = new t_basic_dialog;
	result = army->get_creatures().add_move_bonus( amount, get_type(), days );
	if (result)
	{
		basic_dialog->add_movement( amount / 100 );
		basic_dialog->set_text( get_text( "initial" ) );
	}
	else
	{
		basic_dialog->set_text( get_text( "empty" ) );
	}

	get_adventure_frame()->update();
	basic_dialog->add_ok_button();
	basic_dialog->open( get_dialog_bottom( point ), true, k_align_bottom );
	t_sound_cache music = get_music_playing();
	stop_music();
	get_dialog_sound( k_dialog_sound_power_up )->play( get_sound_volume() );
	basic_dialog->run_modal();
	play_music( music );
}

// --------------------------------------------------------
// all objects which give an army a timed boost to movement
//  -------------------------------------------------------
void t_adv_move_booster::activate_trigger( t_army* army, t_adv_map_point const& point, 
		                                   t_direction direction, t_adventure_frame* frame )
{
	int  amount, days;
	get_bonus(*army, amount, days);
	t_player* owner = army->get_owner();
	if (owner && !owner->is_computer())
		show_dialog( army, amount, days, point );
	else
		army->get_creatures().add_move_bonus( amount, get_type(), days );
}

// --------------------------------------------------------
// all objects which give an army a timed boost to movement
//  -------------------------------------------------------
extern t_external_string const k_text_no_benefit;

std::string  t_adv_move_booster::get_balloon_help() const
{
	t_adventure_frame const* frame = get_adventure_frame();
	t_army const*			 army = frame->get_selected_army();
	std::string				 text;

	text = get_name();

	if (army != 0 && army->get_creatures().get_shortest_bonus( get_type() ) > 0)
	{
		text += " ";
		text += k_text_no_benefit;
	}
	return text;
}

// --------------------------------------------------------
//  -------------------------------------------------------
void t_adv_move_booster::get_bonus( t_creature_array const& array, int &amount, int &days ) const
{
	switch (get_major_subtype())
	{
		case k_movement_stables:
			amount = 500;
			days = 7;
			break;

		case k_movement_oasis:
			amount = 1000;
			days = 1;
			break;

		case k_movement_watering_hole:
			amount = 750;
			days = 1;
			break;

		case k_movement_rally_flag:
			amount = 100;
			days = 28;
			break;
		default:
			assert( false );
	}
}

// --------------------------------------------------------
//  -------------------------------------------------------
float t_adv_move_booster::ai_value( t_adventure_ai const& ai, t_creature_array const& army, int move_cost ) const
{
	int  amount, days;

	get_bonus( army, amount, days );

	if (days > 7) days = 7;

	bool needs_bonus = false;
	for (int i = 0; i < t_creature_array::k_size; i++)
		if ((army[i].get_number() != 0) && !army[i].has_timed_bonus( get_type() ))
			needs_bonus = true;

	if ( !needs_bonus || ( (move_cost > (amount / 2)) && (days == 1) ) )
		return 0.0f;

	float army_value = army.ai_value();

	// I'm making reasonable assumption that a 100% movement bonus for 2 weeks adds 30% to the value of the army.
	return army_value * ( static_cast<float>(amount) / army.get_max_movement() ) * (0.30f * (days / 14.0f));
}


// --------------------------------------------------------
// all objects which give an army a timed boost to movement and
// a pathfinding bonus
//  -------------------------------------------------------
t_adv_pathfinder::t_adv_pathfinder( std::string const& model_name )
                : t_adv_move_booster( model_name )
{
}

// --------------------------------------------------------
// all objects which give an army a timed boost to movement and
// a pathfinding bonus
//  -------------------------------------------------------
void t_adv_pathfinder::activate_trigger( t_army* army, t_adv_map_point const& point, 
		                                 t_direction direction, t_adventure_frame* frame )
{
	t_creature_array&	creatures = army->get_creatures();
	int					i;
	t_creature_stack*	stack;
	t_stat_type			stat;

	// determine which pathfinding bonus to give
	switch (get_major_subtype())
	{
		case k_pathfinder_brimstone_lodge:
			stat = k_stat_mastery_lava;
			break;

		case k_pathfinder_winter_lodge:
			stat = k_stat_mastery_snow;
			break;

		case k_pathfinder_desert_hut:
			stat = k_stat_mastery_sand;
			break;

		case k_pathfinder_barbarians_camp:
			stat = k_stat_mastery_rough;
			break;

		case k_pathfinder_wet_log_inn:
			stat = k_stat_mastery_swamp;
			break;
	}

	for (i = 0; i < t_creature_array::k_size; ++i)
	{
		stack = &creatures[i];
		if (stack->get_number() == 0)
			continue;
		stack->add_timed_bonus( stat, 1, get_type(), 7 );
	}

	t_player* owner = army->get_owner();
	if ( owner && !owner->is_computer() )
		show_dialog( army, 200, 7, point );
}

// --------------------------------------------------------
// -------------------------------------------------------
void t_adv_pathfinder::get_bonus( t_creature_array const& array, int &amount, int &days ) const
{
	float value;

	switch (get_major_subtype())
	{
		case k_pathfinder_brimstone_lodge:
			value = (float)array.get_move_cost( k_terrain_lava );
			break;

		case k_pathfinder_winter_lodge:
			value = (float)array.get_move_cost( k_terrain_snow ) ;
			break;

		case k_pathfinder_desert_hut:
			value = (float)array.get_move_cost( k_terrain_sand );
			break;

		case k_pathfinder_barbarians_camp:
			value = (float)array.get_move_cost( k_terrain_rough );
			break;

		case k_pathfinder_wet_log_inn:
			value = (float)array.get_move_cost( k_terrain_swamp );
			break;
		default:
			value = 0.0f;
	}

	int steps = (int)((array.get_max_movement() / value) 
				* array.get_map()->get_ai().get_rough_coverage());

	if (steps < 2) steps = 2;
	
	amount = (int)((value - 100) * steps);
	days = 7;
}
